package com.bdqn;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Practice1 {
    public static void main(String[] args) {
        Class clz=Person.class;
        String fullName=clz.getName();
        String simpleName=clz.getSimpleName();
        System.out.println("以下是"+fullName+"类的基本信息");
        System.out.println("--------------------------");

        //获取Person类所在的包
        Package pkg=clz.getPackage();
        System.out.println(simpleName+"定义在"+pkg.getName()+"包中");

        //获得clz所表示的实体(类、接口、基本类型或void)的超类的Class
        //如果clz表示 Object类、一个接口、一个基本类型或void，则返回null
        //如果clz表示一个数组类，则返回 Object类的Class实例

        Class superClass=clz.getSuperclass();
        System.out.println(simpleName+"类的超类是:"+superClass.getName());
        System.out.println("---------------------------");

        //获得clz 所表示的类实现的接口
        //如果clz 表示一个不实现任何接口的类或接口，则此方法返回一个长度为0的数组
        //如果clz 表示一个基本类型或void，则此方法返回一个长度为0的数组

        Class [] interfaces=clz.getInterfaces();
        System.out.println(simpleName+"类所实现的接口:");
        for (Class c:interfaces)
            System.out.println("\t"+c.getName());
        System.out.println("-----------------------------");

        //每个修饰符对应一个int常量，返回的修饰符信息将类所拥有的修饰符以“或”运算组合
        //通过与Modifier类中的常量进行“与”运算即可判断该类型是否拥有某个修饰符
        int modifier = clz.getModifiers();
        System.out.println(simpleName+"类的修饰符");
        if((modifier& Modifier.PUBLIC)==Modifier.PUBLIC)
            System.out.println("\t访问修饰符是:public");
        else
            System.out.println("\t访问修饰符是:default(package)");
        if((modifier&Modifier.FINAL)==Modifier.FINAL)
            System.out.println("\t这个类是final的");
        if((modifier&Modifier.ABSTRACT)==Modifier.ABSTRACT)
            System.out.println("\t这是一个抽象类");
        if((modifier&Modifier.INTERFACE)==Modifier.INTERFACE)
            System.out.println("\t这是一个接口");
        System.out.println("----------------------------");

        //获取Person类声明的所有构造方法
        //他们是公共、保护、默认(包)访问和私有构造方法
        //如果此Class 实例表示一个接口、一个基本类型、一个数组类或void，则
        //此方法返回一个长度为0的数组

        Constructor[] cons=Person.class.getDeclaredConstructors();

        //构造方法的一些信息
        System.out.println("=========构造方法展示=========");
        for (Constructor con:cons){
            System.out.print("访问修饰符:");
            modifier = con.getModifiers();
            //判断该构造方法的访问修缮费
            if((modifier&Modifier.PUBLIC)==Modifier.PUBLIC)
                System.out.println("public");
            else if((modifier&Modifier.PROTECTED)==Modifier.PROTECTED)
                System.out.println("protected");
            else if((modifier&Modifier.PRIVATE)==Modifier.PRIVATE)
                System.out.println("private");
            else
                System.out.println("default(package)");

            //获取构造方法的参数列表
            Class[] params=con.getParameterTypes();
            if(params.length==0){
                System.out.println("该构造方法没有参数");
            }else{
                System.out.print("该构造方法的参数列表为:[");
                for (int i=0;i<params.length;i++){
                    if(i!=0)
                        System.out.print(",");
                    System.out.print(params[i].getName());
                }
                System.out.println("]");
            }
            System.out.println("-----------------------------");
        }//构造方法遍历

        //获取Person类中所有属性,
        //包括公共、保护、默认(包)访问和私有属性,但不包括继承的属性,
        //如果该类或接口不声明任何属性，或者此Class实例表示一个基本类型
        //一个数组或void，则此方法返回一个长度为0的数组
        Field[] fields=Person.class.getDeclaredFields();
        //展示属性一些信息
        System.out.println("=========属性展示=========");
        for (Field field:fields){
            System.out.println("属性名:"+field.getName());
            System.out.println("类型:"+field.getType().getName());

            System.out.print("访问修饰符:");
            modifier=field.getModifiers();
            //判断该属性的访问修饰符
            if((modifier&Modifier.PRIVATE)==Modifier.PRIVATE)
                System.out.println("private");
                //判断该属性是否有protected
            else if((modifier&Modifier.PROTECTED)==Modifier.PROTECTED)
                System.out.println("protected");
                //判断该方法是否有public
            else if((modifier&Modifier.PUBLIC)==Modifier.PUBLIC)
                System.out.println("public");
            else
                System.out.println("default(package)");
            //判断该属性是否有static修饰符
            if((modifier& Modifier.STATIC)==Modifier.STATIC)
                System.out.println("这是一个静态属性");
            //判断该属性是否有final修饰符
            if((modifier&Modifier.FINAL)==Modifier.FINAL)
                System.out.println("这是一个final属性");
            System.out.println("-----------------------------");
        }//遍历属性结束

        //获取Person类中所有方法,
        //包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法,
        //如果该类或接口不声明任何方法，或者此Class实例表示一个基本类型
        //一个数组或void，则此方法返回一个长度为0的数组

        Method[] methods=Person.class.getDeclaredMethods();

        //展示方法的一些信息
        System.out.println("==========方法展示=========");
        for (Method method:methods){
            System.out.println("方法名:"+method.getName());
            System.out.println("返回值类型:"+method.getReturnType().getName());

            //获取方法的参数列表
            Class [] params=method.getParameterTypes();
            if (params.length == 0){
                System.out.println("该方法没有参数");
            }else{
                System.out.print("该构造方法的参数列表为：[ ");
                for (int i = 0; i < params.length; i++) {
                    if (i != 0)
                        System.out.print(", ");
                    System.out.print(params[i].getName());
                }
                System.out.println("]");
            }

            System.out.print("访问修饰符:");
            modifier=method.getModifiers();
            //判断该方法的访问修饰符
            if ((modifier & Modifier.PUBLIC) == Modifier.PUBLIC)
                System.out.println("public");
            else if ((modifier & Modifier.PROTECTED) == Modifier.PROTECTED)
                System.out.println("protected");
            else if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE)
                System.out.println("private");
            else
                System.out.println("default(package)");
            //判断该方法是否有static修饰符
            if((modifier& Modifier.STATIC)==Modifier.STATIC)
                System.out.println("这是一个静态方法");
            if((modifier& Modifier.FINAL)==Modifier.FINAL)
                System.out.println("这是一个final方法");
            if((modifier& Modifier.ABSTRACT)==Modifier.ABSTRACT)
                System.out.println("这是一个抽象方法");
            if((modifier& Modifier.SYNCHRONIZED)==Modifier.SYNCHRONIZED)
                System.out.println("这是一个同步方法");

            //获取方法所属的类或接口的Class实例
            Class declaringClass=method.getDeclaringClass();
            System.out.println("方法声明在:"+declaringClass.getName()+"中");

            //获取方法抛出的异常类型,即throws子句中声明的异常
            Class [] exceptions=method.getExceptionTypes();
            if (exceptions.length>0) {
                System.out.print("该方法抛出的异常有:[");
                for (int i=0;i<exceptions.length;i++){
                    if(i!=0)
                        System.out.print(",");
                    System.out.print(exceptions[i].getName());
                }
                System.out.println("]");
            }
            System.out.println("-----------------");
        }//遍历方法
    }
}
